package org.david.android.test;

import org.hibernate.SessionFactory;
import org.junit.Assert;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.unitils.reflectionassert.ReflectionAssert;
import org.unitils.reflectionassert.ReflectionComparatorMode;

/**
 * Spring的支持数据库事务和依赖注入的JUnit 4 TestCase基类简写.
 * 
 */
// 默认载入applicationContext-test.xml,子类中的@ContextConfiguration定义将合并父类的定义.
@ContextConfiguration(locations = { "/applicationContext-test.xml" })
public abstract class SpringTxTestCase extends AbstractTransactionalJUnit4SpringContextTests {

    /**
     * 刷新sessionFactory,强制Hibernate执行SQL以验证ORM配置.
     * 
     * sessionFactory名默认为"sessionFactory".
     * 
     * @see #flush(String)
     */
    protected void flush() {
        flush("sessionFactory");
    }

    /**
     * 刷新sessionFactory,强制Hibernate执行SQL以验证ORM配置. 因为没有执行commit操作,不会更改测试数据库.
     * 
     * @param sessionFactoryName applicationContext中sessionFactory的名称.
     */
    protected void flush(final String sessionFactoryName) {
        ((SessionFactory) applicationContext.getBean(sessionFactoryName)).getCurrentSession().flush();
    }

    /**
     * 将对象从session中消除, 用于测试初对象的始化情况.
     * 
     * sessionFactory名默认为"sessionFactory".
     */
    protected void evict(Object entity) {
        evict(entity, "sessionFactory");
    }

    /**
     * 将对象从session中消除, 用于测试初对象的始化情况.
     * 
     */
    protected void evict(final Object entity, final String sessionFactoryName) {
        ((SessionFactory) applicationContext.getBean(sessionFactoryName)).getCurrentSession().evict(entity);
    }

    /**
     * sleep等待,单位毫秒.
     */
    protected void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
        }
    }

    // Assert 函数 //

    /**
     * 反射比较对象间的所有属性,忽略expected对象的Null对象和集合中对象的次序.
     */
    protected void assertReflectionEquals(Object expected, Object actual) {
        ReflectionAssert.assertReflectionEquals(expected, actual, ReflectionComparatorMode.IGNORE_DEFAULTS, ReflectionComparatorMode.LENIENT_ORDER);
    }

    /**
     * @see #assertReflectionEquals(Object, Object)
     */
    protected void assertReflectionEquals(String message, Object expected, Object actual) {
        ReflectionAssert.assertReflectionEquals(message, expected, actual, ReflectionComparatorMode.IGNORE_DEFAULTS, ReflectionComparatorMode.LENIENT_ORDER);
    }

    protected void assertEquals(Object expected, Object actual) {
        Assert.assertEquals(expected, actual);
    }

    protected void assertEquals(String message, Object expected, Object actual) {
        Assert.assertEquals(message, expected, actual);
    }

    protected void assertTrue(boolean condition) {
        Assert.assertTrue(condition);
    }

    protected void assertTrue(String message, boolean condition) {
        Assert.assertTrue(message, condition);
    }

    protected void assertFalse(boolean condition) {
        Assert.assertFalse(condition);
    }

    protected void assertFalse(String message, boolean condition) {
        Assert.assertFalse(message, condition);
    }

    protected void assertNull(Object object) {
        Assert.assertNull(object);
    }

    protected void assertNull(String message, Object object) {
        Assert.assertNull(message, object);
    }

    protected void assertNotNull(Object object) {
        Assert.assertNotNull(object);
    }

    protected void assertNotNull(String message, Object object) {
        Assert.assertNotNull(message, object);
    }
}
